package com.mxpio.erp.workshop.policy.impl;

import com.mxpio.erp.common.LotStatusUtil;
import com.mxpio.erp.common.enums.InspectionEnums;
import com.mxpio.erp.common.enums.NoticeStatusEnums;
import com.mxpio.erp.common.enums.OrderEnums;
import com.mxpio.erp.common.enums.OrderStatusEnums;
import com.mxpio.erp.common.inventory.entity.Lot;
import com.mxpio.erp.common.inventory.entity.WarehouseOrder;
import com.mxpio.erp.common.inventory.entity.WarehouseOrderLine;
import com.mxpio.erp.common.jpa.model.Notice;
import com.mxpio.erp.common.jpa.model.NoticeLine;
import com.mxpio.erp.common.jpa.model.NoticeLineKey;
import com.mxpio.erp.common.order.policy.AbstractNoticePolicy;
import com.mxpio.erp.common.order.policy.NoticeContext;
import com.mxpio.erp.common.technology.entity.Item;
import com.mxpio.erp.common.vo.OrderExcuteLineVo;
import com.mxpio.erp.common.workshop.entity.OODefectiveProductsNoticeLine;
import com.mxpio.erp.common.workshop.entity.OoPickingNotice;
import com.mxpio.erp.common.workshop.entity.OutsourceOrder;
import com.mxpioframework.common.util.BeanReflectionUtils;
import com.mxpioframework.jpa.JpaUtil;
import org.apache.commons.collections4.CollectionUtils;

import java.util.*;

/**
 * 委外不良品退料通知单执行策略
 * @author mxpio
 *
 */
public class DefaultOODefectiveNoticePolicy extends AbstractNoticePolicy {

	private List<OrderExcuteLineVo> orderExcuteVos;

	public DefaultOODefectiveNoticePolicy(List<OrderExcuteLineVo> orderExcuteVos) {
		this.orderExcuteVos = orderExcuteVos;
	}

	@Override
	public void execute(NoticeContext context) {

	}

	@Override
	public NoticeContext config(NoticeContext context) {
		context.setOrderExcuteVos(orderExcuteVos);
		return context;
	}

	//重写apply方法，根据执行提交的明细数据，是否补料。直接生成一个对应的补料通知单。同时更新原通知单明细中的异常信息登记字段
	@Override
	public void apply(NoticeContext context) {
		if(beforeExecute(context)) {
			execute(context);
			Notice notice = context.getEntity();
			List<OrderExcuteLineVo> orderExcuteVos = context.getOrderExcuteVos();
			WarehouseOrder wo = null;
			int lineNo = 0;
			//补料通知单
			Map<String, OoPickingNotice> noticeAddMap = new HashMap<>();
			Map<String,List<OrderExcuteLineVo>> voAddMap = new HashMap<>();
			Map<String, OutsourceOrder> orderMap = new HashMap<>();
			for(OrderExcuteLineVo vo : orderExcuteVos){
				//回写不良品退料通知单明细中的字段数据
				NoticeLineKey noticeLineKey = new NoticeLineKey();
				noticeLineKey.setNoticeNo(vo.getNoticeNo());
				noticeLineKey.setLineNo(vo.getNoticeLineNo());
				OODefectiveProductsNoticeLine dBDefectiveProductsNoticeLine = JpaUtil.getOne(OODefectiveProductsNoticeLine.class, noticeLineKey);
				if (dBDefectiveProductsNoticeLine!=null){
					dBDefectiveProductsNoticeLine.setReporter(vo.getReporter());
					dBDefectiveProductsNoticeLine.setReportProc(vo.getReportProc());
					dBDefectiveProductsNoticeLine.setExceptionType(vo.getExceptionType());
					dBDefectiveProductsNoticeLine.setDefectiveReason(vo.getDefectiveReason());
					dBDefectiveProductsNoticeLine.setDefectiveDesc(vo.getDefectiveDesc());
					dBDefectiveProductsNoticeLine.setResponseUnit(vo.getResponseUnit());
					JpaUtil.update(dBDefectiveProductsNoticeLine);
				}
				//处理补料通知单
				if ("1".equals(vo.getSupplementFlag())
						||"Y".equals(vo.getSupplementFlag())
						||"是".equals(vo.getSupplementFlag())){//是否需要生成补料通知单
					OoPickingNotice noticeAdd = noticeAddMap.get(vo.getBomWhCode());
					if(noticeAdd == null) {
						noticeAdd = (OoPickingNotice) BeanReflectionUtils.newInstance(OoPickingNotice.class);
						OutsourceOrder order = null;//源生产订单
						if (orderMap.containsKey(vo.getBizOrderNo())){
							order = orderMap.get(vo.getBizOrderNo());
						}else{
							order = JpaUtil.getOne(OutsourceOrder.class, vo.getBizOrderNo());
							if (order!=null){
								orderMap.put(vo.getBizOrderNo(),order);
							}
						}
						//关联生产订单业务字段
						if (order!=null){
							noticeAdd.setPnCode(order.getPnCode());
							noticeAdd.setPnName(order.getPnName());
							noticeAdd.setStartDate(order.getStartDate());
							noticeAdd.setEndDate(order.getEndDate());
							noticeAdd.setProductItemCode(order.getProductItemCode());
							noticeAdd.setProductItemName(order.getProductItemName());
							noticeAdd.setProductDrawingNo(order.getProductDrawingNo());
						}

						noticeAdd.setBizOrderNo(vo.getBizOrderNo());
						noticeAdd.setNoticeDate(new Date());
						noticeAdd.setWhCode(vo.getBomWhCode());//取原订单bom子表中的仓库信息
						noticeAdd.setAccessType(OrderEnums.AccessType.OUT.getCode());
						noticeAdd.setPickingType(NoticeStatusEnums.NoticeType.OO_M_REOUT.getCode());//委外补料
						noticeAdd.setNoticeStatus(NoticeStatusEnums.NoticeStatus.CREATE.getStatusCode());

						noticeAddMap.put(vo.getBomWhCode() , noticeAdd);
						voAddMap.put(vo.getBomWhCode() , new ArrayList<OrderExcuteLineVo>());
					}
					voAddMap.get(vo.getBomWhCode()).add(vo);
				}
				//生产仓单
				lineNo++;
				if(wo == null){
					wo = new WarehouseOrder();
					wo.setAccessType(notice.getAccessType());
					wo.setBpmnStatus(OrderStatusEnums.BpmnStatus.AUDITED.getStatusCode());
					wo.setCloseStatus(OrderStatusEnums.CloseStatus.OPEN.getStatusCode());
					wo.setOrderStatus(OrderStatusEnums.OrderStatus.PLAN.getStatusCode());
					wo.setOrderDate(new Date());
					wo.setOriginBizNo(vo.getBizOrderNo());
					wo.setWhCode(vo.getWhCode());//前端已经传递报废属性的仓库
					//wo.setWhCode(warehouseList.get(0).getWhCode());//生成的仓单对应的仓库应该是仓储属性是报废的仓库
					wo.setWoType(notice.getPickingType());
					wo.setOriginNoticeNo(notice.getNoticeNo());//关联noticeno字段
					JpaUtil.save(wo);
				}
				WarehouseOrderLine line = new WarehouseOrderLine();
				line.setWhCode(wo.getWhCode());
				line.setCloseStatus(OrderStatusEnums.CloseStatus.OPEN.getStatusCode());
				Item item = JpaUtil.linq(Item.class).idEqual(vo.getItemCode()).findOne();
				line.setItemCode(vo.getItemCode());
				line.setItemGroupCode(item.getItemGroupCode());
				line.setItemName(item.getItemName());
				line.setItemSpec(item.getItemSpec());
				line.setUnitCode(item.getUnitCode());
				line.setDrawingNo(item.getDrawingNo());
				line.setQuantity(vo.getQuantity());
				line.setBizNo(wo.getBizNo());
				line.setLineNo(lineNo+"");
				line.setOriginBizNo(vo.getBizOrderNo());
				line.setOriginBizLineNo(vo.getBizOrderlineNo());
				line.setSort(vo.getSort());
				line.setLotNo(vo.getLotNo());//
				//line.setSubLotIndex(vo.getSubLotIndex());
				//拆批 新生成批次索引
				Long count = JpaUtil.linq(Lot.class).equal("lotNo", vo.getLotNo()).count();
				line.setSubLotIndex(count.toString());//子批索引
				//
				Lot lot = new Lot();
				lot.setLotNo(vo.getLotNo());
				String binaryString = LotStatusUtil.toBinaryString("0");//默认正常
				lot.setLotStatus(LotStatusUtil.switchBinaryByIndex(binaryString, InspectionEnums.LotStatusBitIndex.IB14.getIndex()));

				lot.setSubLotIndex(line.getSubLotIndex());
				JpaUtil.save(lot);

				line.setOriginNoticeNo(notice.getNoticeNo());
				line.setOriginNoticeLineNo(vo.getNoticeLineNo());
				JpaUtil.save(line);
			}
			// 生成补料通知单明细
			if (!noticeAddMap.isEmpty()){
				for(Map.Entry<String,OoPickingNotice> entry : noticeAddMap.entrySet()) {
					Notice addnotice = entry.getValue();
					JpaUtil.save(addnotice);
					int innerlineNo = 0;
					for(OrderExcuteLineVo vo : voAddMap.get(entry.getKey())) {
						innerlineNo++;
						NoticeLine line = addnotice.createLine(vo);
						line.setLineNo(innerlineNo+"");
						line.setLotNo("");//去掉批次信息
						Item item = JpaUtil.linq(Item.class).idEqual(vo.getItemCode()).findOne();
						line.setItemName(item.getItemName());
						line.setItemSpec(item.getItemSpec());
						line.setUnitCode(item.getUnitCode());
						line.setDrawingNo(item.getDrawingNo());
						JpaUtil.save(line);
					}
				}
			}
			afterExecute(context);
			notice.setNoticeStatus(NoticeStatusEnums.NoticeStatus.CONFIRM.getStatusCode());
			JpaUtil.update(notice);
		} else {
			if(CollectionUtils.isEmpty(context.getErrors())) {
				context.addError("前置校验不通过");
			}
		}

	}

	@Override
	public boolean beforeExecute(NoticeContext context) {
		return true;
	}

	@Override
	public void afterExecute(NoticeContext context) {
		
	}

}
